package com.wing.productionPlan.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wing.common.enums.MaintenanceEnum;
import com.wing.common.utils.JsonResult;
import com.wing.enterprise.feign.EnterpriseClient;
import com.wing.enterprise.product.model.entity.ProductDetail;
import com.wing.enterprise.product.model.entity.ResBenchmarkBookEchnology;
import com.wing.productionPlan.dao.ProductionPlanRecordDao;
import com.wing.productionPlan.model.entity.*;
import com.wing.productionPlan.model.request.DeviceTypeForm;
import com.wing.productionPlan.model.response.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 排产记录-ServiceImpl
 *
 * @author xiayang
 */
@Service
@Slf4j
public class ProductionPlanRecordServiceImpl extends ServiceImpl<ProductionPlanRecordDao, ProductionPlanRecord> implements ProductionPlanRecordService {

    @Autowired
    private EnterpriseClient enterpriseClient;

    @Autowired
    private  QualityTestingRecordDetailService qualityTestingRecordDetailService;

    @Autowired
    private  ProductionProcessDeviceService productionProcessDeviceService;

    @Autowired
    private ProductionProcessMaterialService productionProcessMaterialService;

    @Autowired
    private ProductionProcessService productionProcessService;

    @Autowired
    private ProductionPlanRecordService productionPlanRecordService;




    @Override
    public Page<ProductionPlanRecordVO> pageList(Page page, Map<String, Object> params) {
        List<ProductionPlanRecordVO> list = this.baseMapper.pageList(page, params);
        page.setRecords(list);
        return page;
    }

    @Override
    public ProductionPlanRecordVO get(Long id) {
        return this.baseMapper.get(id);
    }

    /**
     * 查询排产记录信息
     * @param type 类型 1.整体排产 2.工序排产
     * @param productionPlanRecordId 排产记录id
     * @param bookId 整体排产需要
     * @param processId 工序排产需要
     * @return
     */
    @Override
    public JsonResult getRecordDetailBy(String type, Long productionPlanRecordId, Long bookId, Long processId) {
        if (ObjectUtil.isNull(productionPlanRecordId)){
            return JsonResult.fail("排产记录id未传入");
        }
        //查询排产记录信息
        ProductionPlanRecord byId = this.getById(productionPlanRecordId);
        //整体排产
        List<ProcessPlanRecordAllDetailVo> allDetailVos = new ArrayList<>();
        if ("entirety".equals(type)){
            if (ObjectUtil.isNull(bookId)){
                return JsonResult.fail("基准书id未传入！");
            }
            //1. 查询基书的工序列表
//            List<ResBenchmarkBookEchnology> processInfoBy = enterpriseClient.getProcessInfoBy(bookId);
            QueryWrapper<ProductionProcess> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("production_plan_record_id", productionPlanRecordId);
            queryWrapper.eq("production_plan_id", byId.getProductionPlanId());
            queryWrapper.eq("is_deleted", false);
            List<ProductionProcess> processInfoBy = this.productionProcessService.list(queryWrapper);
            if (CollectionUtil.isEmpty(processInfoBy)){
                return JsonResult.fail("基准书未查询到工序");
            }
            for (ProductionProcess productionProcess : processInfoBy) {

                ProcessPlanRecordAllDetailVo allDetailVo = new ProcessPlanRecordAllDetailVo();
                allDetailVo.setId(productionProcess.getId());
                allDetailVo.setName(productionProcess.getProcessName());
                //2. 查询出已排产的数据
                Map<String, Object> processOutputAndYield = qualityTestingRecordDetailService
                        .getProcessOutputAndYield(byId.getProductionPlanId(), productionPlanRecordId);
                if (ObjectUtil.isNotNull(processOutputAndYield)){
                    allDetailVo.setPlanQuantity(String.valueOf(processOutputAndYield.get("planQuantity")));
                    allDetailVo.setProductionQuantity(String.valueOf(processOutputAndYield.get("productionQuantity")));
                    allDetailVo.setYield(String.valueOf(processOutputAndYield.get("yield")));
                }


                String deviceTypes = productionProcess.getDeviceTypes();
                if (StrUtil.isNotBlank(deviceTypes)){
                    List<String> list = Arrays.asList(deviceTypes.split(","));
                    List<DeviceOrWorkVo> devicelist = productionProcessService.devicelist(list);
                    List<DeviceOrWorkVo> fessionlist = productionProcessService.fessionlist(list);
                    if (CollectionUtil.isNotEmpty(devicelist)){
                        allDetailVo.setWorkstationNature(MaintenanceEnum.workstationEmum.SBGW.getCode());
                        allDetailVo.setWorkstationNatureName(MaintenanceEnum.workstationEmum.SBGW.getName());
                        allDetailVo.setDeviceTypeList(devicelist);
                        
                    }else if (CollectionUtil.isNotEmpty(fessionlist)){
                        allDetailVo.setWorkstationNature(MaintenanceEnum.workstationEmum.RGGW.getCode());
                        allDetailVo.setWorkstationNatureName(MaintenanceEnum.workstationEmum.RGGW.getName());
                        allDetailVo.setDeviceTypeList(fessionlist);
                    }
                }
                //3. 查询机台排产数据
//                List<ProductionProcessDeviceVO> processDeviceByProcessId = productionProcessDeviceService
//                        .getProcessDeviceByProcessId(byId.getProductionPlanId(), productionPlanRecordId, resBenchmarkBookEchnology.getProcessId());
//                allDetailVo.setProductionProcessDevices(processDeviceByProcessId);

                //4. 查看工序物料信息
                List<RecordMaterialSkuVo> skuVos = productionProcessMaterialService
                        .getMaterialInfoBy(byId.getProductionPlanId(),productionPlanRecordId,productionProcess.getId());
                allDetailVo.setRecordMaterialSkuVos(skuVos);
                ResBenchmarkBookEchnology processInfoByProcessId = this.enterpriseClient.getProcessInfoByProcessId(productionProcess.getProcessId());
                allDetailVo.setResBenchmarkBookEchnology(processInfoByProcessId);
                allDetailVos.add(allDetailVo);
            }
            return JsonResult.success(allDetailVos);

        }
        //工序排产
        else if("process".equals(type)){
            if (ObjectUtil.isNull(processId)){
                return JsonResult.fail("具体工序id未传入！");
            }

//            ResBenchmarkBookEchnology processInfoByProcessId = enterpriseClient.getProcessInfoByProcessId(processId);
            QueryWrapper<ProductionProcess> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("production_plan_record_id", productionPlanRecordId);
            queryWrapper.eq("production_plan_id", byId.getProductionPlanId());
            queryWrapper.eq("process_id", processId);
            queryWrapper.eq("is_deleted", false);
            ProductionProcess one = this.productionProcessService.getOne(queryWrapper);
            ProcessPlanRecordAllDetailVo allDetailVo = new ProcessPlanRecordAllDetailVo();
            if (ObjectUtil.isNotNull(one)){
                allDetailVo.setId(one.getId());
                allDetailVo.setName(one.getProcessName());
            }
            //2. 查询出已排产的数据
            Map<String, Object> processOutputAndYield = qualityTestingRecordDetailService.getProcessOutputAndYield(byId.getProductionPlanId(), productionPlanRecordId);
            if (ObjectUtil.isNotNull(processOutputAndYield)){
                allDetailVo.setPlanQuantity(String.valueOf(processOutputAndYield.get("planQuantity")));
                allDetailVo.setProductionQuantity(String.valueOf(processOutputAndYield.get("productionQuantity")));
                allDetailVo.setYield(String.valueOf(processOutputAndYield.get("yield")));
            }
            ResBenchmarkBookEchnology processInfoByProcessId = this.enterpriseClient.getProcessInfoByProcessId(processId);
            allDetailVo.setResBenchmarkBookEchnology(processInfoByProcessId);

            String deviceTypes = one.getDeviceTypes();
            if (StrUtil.isNotBlank(deviceTypes)){
                List<String> list = Arrays.asList(deviceTypes.split(","));
                List<DeviceOrWorkVo> devicelist = productionProcessService.devicelist(list);
                List<DeviceOrWorkVo> fessionlist = productionProcessService.fessionlist(list);
                if (CollectionUtil.isNotEmpty(devicelist)){
                    allDetailVo.setWorkstationNature(MaintenanceEnum.workstationEmum.SBGW.getCode());
                    allDetailVo.setWorkstationNatureName(MaintenanceEnum.workstationEmum.SBGW.getName());
                    allDetailVo.setDeviceTypeList(devicelist);

                }else if (CollectionUtil.isNotEmpty(fessionlist)){
                    allDetailVo.setWorkstationNature(MaintenanceEnum.workstationEmum.RGGW.getCode());
                    allDetailVo.setWorkstationNatureName(MaintenanceEnum.workstationEmum.RGGW.getName());
                    allDetailVo.setDeviceTypeList(fessionlist);
                }
            }

            //3. 查询机台排产数据
//            List<ProductionProcessDeviceVO> processDeviceByProcessId = productionProcessDeviceService.getProcessDeviceByProcessId(byId.getProductionPlanId(), productionPlanRecordId, processId);
//            allDetailVo.setProductionProcessDevices(processDeviceByProcessId);

            //4. 查看工序物料信息
            List<RecordMaterialSkuVo> skuVos = productionProcessMaterialService.getMaterialInfoBy(byId.getProductionPlanId(),productionPlanRecordId,one.getId());
            allDetailVo.setRecordMaterialSkuVos(skuVos);
            allDetailVos.add(allDetailVo);
            return JsonResult.success(allDetailVos);
        }else{
            return JsonResult.fail("未匹配到类型or类型传入有误");
        }
    }

    /**
     * 查询物料信息
     * @param processId 工序id
     * @param planRecordId 排产记录/制造令id
     * @return
     */
    @Override
    public JsonResult getMaterialBy(String processId, String planRecordId,Page page, Map<String,Object> paramMap) {
        if (ObjectUtil.isNull(processId) || ObjectUtil.isNull(planRecordId)) {
            return JsonResult.fail("参数有误！");
        }
        ProductionProcess byId = this.productionProcessService.getById(processId);
        if (ObjectUtil.isNotNull(byId)) {
            QueryWrapper<ProductionProcessMaterial> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("plan_record_id", planRecordId);
            queryWrapper.eq("process_id", byId.getProcessId());
            List<ProductionProcessMaterial> list = this.productionProcessMaterialService.list(queryWrapper);
            //拿到所有的skuCode
            if (CollectionUtil.isNotEmpty(list)){
                Set<String> collected = list.stream()
                        .filter(info->StrUtil.isNotEmpty(info.getSkuCode()))
                        .map(ProductionProcessMaterial::getSkuCode)
                        .collect(Collectors.toSet());
                List<ProductDetail> details = this.productionProcessService.getSkuInfoBy(collected,page,paramMap);
                return JsonResult.success(details);
            }
        } else {
            return JsonResult.fail("参数有误！");
        }
        return JsonResult.success("");
    }

    @Override
    public  Page<ProductDetail> getMaterialOthers(Page page, Map<String,Object> paramMap) {
        List<ProductDetail> details = this.productionProcessService.getSkuInfoBy(null,page,paramMap);
        page.setRecords(details);
        return page;
    }

    /**
     * 查询在制信息
     * @param pg 分页参数
     * @param paramMap 入参
     * @return
     */
    @Override
    public IPage<ProductionPlanRecordReportVO> getPlanRecordCountByIn(Page<ProductionPlanRecordReportVO> pg, Map<String, Object> paramMap) {
        List<ProductionPlanRecordReportVO> vos = this.baseMapper.getPlanRecordCountByIn(pg,paramMap);
        pg.setRecords(vos);
        return pg;
    }

    /**
     * 查询产品库存
     * @param collect productId
     * @return
     */
    @Override
    public List<ProductCountInWarhousesVo> warehouseKc(List<Long> collect) {
        return this.baseMapper.warehouseKc(collect);
    }

    /**
     * 查询排产数
     * @param collect
     * @return
     */
    @Override
    public List<ProductionPlanProDetailVO>  getplanCountBySkuList(List<Long> collect) {
        return baseMapper.getplanCountBySkuList(collect);
    }

    /**
     * 查询合格数不合格数
     * @param collect
     * @return
     */
    @Override
    public List<ProductionPlanProDetailVO> getWorkOrderCountBySkuList(List<Long> collect) {
        return baseMapper.getWorkOrderCountBySkuList(collect);
    }

    /**
     * 查询入库数
     * @param collect
     * @return
     */
    @Override
    public List<ProductionPlanProDetailVO> getInWarehouseList(List<Long> collect) {
        return baseMapper.getInWarehouseList(collect);
    }

    /**
     * 在制品详情
     * @param productDetailId 物料id
     * @return
     */
    @Override
    public ProductionPlanRecordReportDetailVO getProgressDetailBy(Long productDetailId) {
        //在制品详情
        ProductionPlanRecordReportDetailVO detailVO = new ProductionPlanRecordReportDetailVO();
        detailVO.setProductDetailId(productDetailId);

        //查询按工序分类信息
        List<ProcessReportDetailVO> processReportDetails = this.baseMapper.getProcessReportDetailBy(productDetailId);
        detailVO.setProcessReportDetailVo(processReportDetails);
        if (CollectionUtil.isNotEmpty(processReportDetails)) {
            for (ProcessReportDetailVO processReportDetail : processReportDetails) {
                if (ObjectUtil.isEmpty(processReportDetail.getReportedQuantity()) || processReportDetail.getReportedQuantity().compareTo(BigDecimal.ZERO)<=0){
                    processReportDetail.setProcessCompletionRate(BigDecimal.ZERO);
                }else{
                    BigDecimal result =  processReportDetail.getReportedQuantity().divide(BigDecimal.valueOf(processReportDetail.getProductionPlanQuantity()),2, RoundingMode.HALF_UP);
                    BigDecimal percentage = result.multiply(new BigDecimal(100));
                    processReportDetail.setProcessCompletionRate(percentage);
                }
            }
        }

        //查询按制造令分类信息
        List<PlanRecordReportDetailVo> planRecordReportDetails = this.baseMapper.getPlanRecordReportDetails(productDetailId);
        if (CollectionUtil.isNotEmpty(planRecordReportDetails)) {
            //拿到制造令的 入库信息
            //查询物料信息
            Set<Long> collect = planRecordReportDetails.stream()
                    .map(PlanRecordReportDetailVo::getPlanRecordId)
                    .filter(getPlanRecordId -> ObjectUtil.isNotEmpty(getPlanRecordId))
                    .collect(Collectors.toSet());

            List<ProductionPlanRecordWareHouseDetailVO> warehouses  = this.baseMapper.getInWarehouseByPlanRecord(collect);
            if (CollectionUtil.isNotEmpty(warehouses)) {
                for (PlanRecordReportDetailVo planRecordReportDetail : planRecordReportDetails) {
                    for (ProductionPlanRecordWareHouseDetailVO warehouse : warehouses) {
                        if (planRecordReportDetail.getPlanRecordId().equals(warehouse.getPlanRecordId())) {
                            planRecordReportDetail.setInWarehouseQuantity(warehouse.getInWarehouseQuantity());
                        }
                    }

                    //计算达成率
                    if (ObjectUtil.isEmpty(planRecordReportDetail.getInWarehouseQuantity()) || planRecordReportDetail.getInWarehouseQuantity().compareTo(BigDecimal.ZERO)<=0){
                        planRecordReportDetail.setPlanRecordCompletionRate(BigDecimal.ZERO);
                    }else{
                        BigDecimal result =  planRecordReportDetail.getInWarehouseQuantity().divide(planRecordReportDetail.getProductionPlanQuantity(),2, RoundingMode.HALF_UP);
                        BigDecimal percentage = result.multiply(new BigDecimal(100));
                        planRecordReportDetail.setPlanRecordCompletionRate(percentage);
                    }
                }
            }
        }
        detailVO.setPlanRecordReportDetailVos(planRecordReportDetails);
        return detailVO;
    }

}
